package com.tarena.lbs.basic.web.service;

import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.basic.web.dao.repository.AdminRepository;
import com.tarena.lbs.basic.web.dao.repository.UserRepository;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.UserPO;
import com.tarena.lbs.pojo.passport.param.AdminLoginParam;
import com.tarena.lbs.pojo.passport.param.UserLoginParam;
import com.tarena.lbs.pojo.passport.vo.LoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LoginService {
    //仓储层 和持久层 统称为数据层
    //当前项目中 一个表格对应一套数据层(repository mapper) 命名以表格为准 lbs_admin AdminRepository AdminMapper
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private JwtEncoder jwtEncoder;
    /**
     * @param param
     * @return
     * 了解入参 了解出参
     */
    public LoginVO adminLogin(AdminLoginParam param) throws BusinessException {
        //1.读取用户数据 使用phone 不允许电话号码重复 肯定只有一个
        AdminPO adminPO=getAdminByPhone(param.getPhone());
        //2.判断是否存在 把if-满足条件-抛异常 换成 断言
        Asserts.isTrue(adminPO==null,new BusinessException("-2","管理员不存在"));
        //3.对比 入参密码 和 查询adminPO密码是否一致 如果不一致 抛异常
        boolean match=matchPassword(param.getPassword(),adminPO.getAccountPassword());
        //4.断言 不相等 match是false抛异常
        Asserts.isTrue(!match,new BusinessException("-2","密码不正确"));
        //5.使用查询到的admin 封装 jwt
        String jwt=generateJwt(adminPO.getId(), adminPO.getNickname(),adminPO.getAccountType()==0? Roles.ADMIN:Roles.SHOP);
        //6.封装loginVO对象返回
        LoginVO vo=new LoginVO(jwt,adminPO.getId(),adminPO.getNickname());
        return vo;
        /*if (adminPO==null){
            //2个参数 第一个是 code 0 1 2 3 4 -2 第二个是message 异常信息 也是返回的信息
            throw new BusinessException("-2","管理员不存在");
            //系统开发中 2大类异常
            // 一种是系统异常 IOException Syntex ConnectionRefused等
            // 可控的 业务异常 比如 NonAdminExistsException PasswordNotMatchException
            // 一种业务 出现的异常 封装一个异常类 好处 定位简单 日志 成本太高
        }*/
    }
    private AdminPO getAdminByPhone(String phone) {
        //调用仓储层 查询 lbs_admin数据 select * from lbs_admin where account_phone=#{phone}
        //查到返回po 查不到返回null
        QueryWrapper<AdminPO> query=new QueryWrapper<>();
        query.eq("account_phone",phone);
        return adminRepository.getOne(query);
    }
    private boolean matchPassword(String password, String accountPassword) {
        //有一个是空 就不配 相等
        return StringUtils.equals(password,accountPassword);
    }
    private String generateJwt(Integer id,String nickname,Roles role) throws BusinessException {
        //1.到底要在 jwt携带什么数据 jwt携带的内容 不能包含敏感数据 对外名为 password
        //在jwt携带的数据是认证的数据 需要专门封装准备一个认证对象 UserPrinciple (UserAuthentication)
        UserPrinciple userPrinciple=new UserPrinciple();
        userPrinciple.setId(id);
        userPrinciple.setNickname(nickname);
        //根据adminPO中的type类型数据 0 1 判断角色值
        userPrinciple.setRole(role);
        //2.生成的jwtEncoder对象如何创建
        //JwtEncoder jwtEncoder=new JwtEncoder();
        return jwtEncoder.generateToken(userPrinciple);
    }

    public LoginVO userLogin(UserLoginParam userLoginParam) throws BusinessException {
        //1.使用手机号 查询 userPO
        String phone = userLoginParam.getPhone();
        UserPO po=getUserByPhone(phone);
        //2.判断存在
        Asserts.isTrue(po==null,new BusinessException("-2","电话号码不正确"));
        //3.提交的密码 对比 po的密码
        boolean match=matchPassword(userLoginParam.getPassword(),po.getPassword());
        //4.判断是否相等
        Asserts.isTrue(!match,new BusinessException("-2","密码不正确"));
        //5.提供 jwt生成入参 id,nickname,role
        String jwt=generateJwt(po.getId(),po.getNickName(),Roles.USER);
        //6.封装loginVO 返回
        return new LoginVO(jwt,po.getId(),po.getNickName());
    }

    private UserPO getUserByPhone(String phone) {
        //select * from lbs_user where phone=#{}
        QueryWrapper<UserPO> query=new QueryWrapper<>();
        query.eq("phone",phone);
        return userRepository.getOne(query);
    }
}
